﻿/************************************************************************

   Extended Silverlight Toolkit

   Copyright (C) 2010-2012 Xceed Software Inc.

   This program is provided to you under the terms of the Microsoft Public
   License (Ms-PL) as published at http://extendedsilverlight.codeplex.com/license

   Please purchase a commercial version of this toolkit if you are using
   it in a commercial product. The commercial versions support the project,
   and also include more features for each control, priority support,
   source code, updates, removed watermark, and a proprietary license.

   Visit http://xceed.com and follow @datagrid on Twitter.

  **********************************************************************/

using System;
using System.Diagnostics;

namespace Xceed.Silverlight.Data
{
  [DebuggerDisplay( "DummyPosition<T>( UseBaseItem={m_useBaseItem}, BaseItem={m_baseItem}, BasePosition={m_baseSourcePosition}, Offset={m_baseOffset}, RealPosition={m_realPosition} )" )]
  internal class DummyPosition<T> : SourcePosition
  {
    internal DummyPosition( SourcePosition position, long positionOffset, bool approximateOffset )
    {
      if( position == null )
        throw new ArgumentNullException( "position" );

      if( position is ItemPosition )
      {
        if( !( ( ( ItemPosition )position ).Item is T ) )
          throw new InvalidOperationException( "The ItemPosition must contain a valid item of the generic type." );
      }

      m_useBaseItem = false;
      m_baseSourcePosition = position;
      m_baseOffset = positionOffset;
      m_approximateOffset = approximateOffset;
    }

    internal DummyPosition( T baseItem )
      : this( baseItem, 0, false )
    {
    }

    internal DummyPosition( T baseItem, long positionOffset, bool approximateOffset )
    {
      m_useBaseItem = true;
      m_baseItem = baseItem;
      m_baseOffset = positionOffset;
      m_approximateOffset = approximateOffset;
    }

    public bool BasedOnItem
    {
      get
      {
        return m_useBaseItem;
      }
    }

    public T BaseItem
    {
      get
      {
        if( !this.BasedOnItem )
          throw new InvalidOperationException( "The position is not based on an item." );

        return m_baseItem;
      }
    }

    public SourcePosition BaseSourcePosition
    {
      get
      {
        if( this.BasedOnItem )
          throw new InvalidOperationException( "The position is not based on a source position." );

        return m_baseSourcePosition;
      }
    }

    public long BaseOffset
    {
      get
      {
        return m_baseOffset;
      }
    }

    public bool BaseApproximateOffset
    {
      get
      {
        return m_approximateOffset;
      }
    }

    #region RealPosition Property

    internal SourcePosition RealPosition
    {
      get
      {
        return m_realPosition;
      }
      set
      {
        if( value == null )
          throw new ArgumentNullException( "RealPosition" );

        Debug.Assert( m_realPosition == null );
        Debug.Assert( !( value is DummyPosition<T> ) );

        m_realPosition = value;
      }
    }

    #endregion RealPosition Property

#if DEBUG
    public override string ToString()
    {
      object baseData;
      if( m_useBaseItem )
      {
        baseData = m_baseItem;
      }
      else
      {
        baseData = m_baseSourcePosition;
      }

      string approxStr = (m_approximateOffset) ? " approx" : "";

      return string.Format( "DummyPos(base={0}, offset={1}{2})", baseData, m_baseOffset, approxStr );
    }
#endif  //DEBUG


    #region Private Fields

    private bool m_useBaseItem; //false
    private T m_baseItem; //null
    private SourcePosition m_baseSourcePosition;
    private long m_baseOffset; //0
    private bool m_approximateOffset;
    private SourcePosition m_realPosition;

    #endregion Private Fields
  }
}
